package cn.campus.controller.article;

import cn.campus.constant.article.CookiePrefix;
import cn.campus.constant.article.FileConstant;
import cn.campus.constant.article.PatternConstant;
import cn.campus.converter.ArticleDTOToArticleVOConverter;
import cn.campus.enums.article.ArticleStatus;
import cn.campus.enums.article.FileSuffixEnum;
import cn.campus.enums.article.ResultEnum;
import cn.campus.exception.article.ArticleException;
import cn.campus.pojo.User;
import cn.campus.pojo.article.dto.ArticleDTO;
import cn.campus.pojo.article.dto.PageInfo;
import cn.campus.pojo.article.forms.ArticleForm;
import cn.campus.pojo.article.vo.ArticleVO;
import cn.campus.pojo.article.vo.ResultVO;
import cn.campus.service.article.ArticleService;
import cn.campus.util.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.util.List;

/**
 * 文章控制器
 * Created by linyanbin on 2018/9/15.
 */
@RestController
@RequestMapping("/api/articles")
@Slf4j
public class ArticleController {

    @Autowired
    private ArticleService articleService;

    /**
     * 创建文章
     * @param articleForm 前端提交表单
     * @param file  上传的文件
     * @param request 请求
     * @return
     */
    @RequestMapping(method = RequestMethod.POST)
    public ResultVO<Object> createArticle(ArticleForm articleForm, @RequestParam("file") MultipartFile file, HttpServletRequest request) {
        User user = (User) request.getSession().getAttribute("user");
        if (user == null) {
            throw new ArticleException(ResultEnum.USER_NOT_LOGIN);
        }
        articleForm.setFromId(user.getUser_id());
        // 根据文章内容简单生成文章摘要
        String summary = TextUtil.htmm2Text(articleForm.getArticleContent());
        if (summary.length() > 50) {
            summary = summary.substring(0, 50) + "..."; // 截取文章前50字作为摘要
        }
        articleForm.setArticleSummary(summary);
        // 创建上传文件的目录，/files/article/yyyy/MM/dd/
        String relativePath = FileConstant.ARTICLE_IMG_RELATIVE_PATH + DateUtils.getcurrentDateString(PatternConstant.DATE_PATTERN);
       // 项目路径/WEB-INF/files/article/yyyy/MM/dd/
        String realPath = request.getServletContext().getRealPath(FileConstant.WEB_INF + relativePath);
        File directoryFile = new File(realPath);
        if (!directoryFile.exists()) {
            directoryFile.mkdirs();
        }
        if (!file.isEmpty()) {
            saveDetail(articleForm, relativePath, realPath, file);
        }
        return ResultVoUtils.success();
    }

    /**
     * 获取一篇文章的信息，包含发表文章的用户信息
     * @param articleId 文章ID
     * @return
     */
    @RequestMapping(value = "/{articleId}", method = RequestMethod.GET)
    public ResultVO<ArticleVO> findOne(@PathVariable("articleId") String articleId, HttpServletRequest req,
                                       HttpServletResponse res) {
        // 获取存储上次访问的时间戳的Cookie，利用时间戳防止用户一直刷新文章
        Cookie cookie = CookieUtil.getCookie(req, CookiePrefix.ARTICLE_LAST_VISIT_TIME + articleId);
        long intervalVisitTime = 0;
        if (cookie != null) {
            // 获取存储上次访问的时间戳
            String lastVisitTimeMillis = cookie.getValue();
            // 计算间隔访问时间戳
            intervalVisitTime = System.currentTimeMillis() - Long.parseLong(lastVisitTimeMillis);
        }
        ArticleDTO articleDTO = articleService.findById(articleId, intervalVisitTime);
        ArticleVO articleVO = ArticleDTOToArticleVOConverter.convert(articleDTO);
        articleVO.setArticleContent(articleDTO.getArticleContent());    // 将内容设置回来
        CookieUtil.addCookie(res, CookiePrefix.ARTICLE_LAST_VISIT_TIME + articleId, ""+System.currentTimeMillis());
        return ResultVoUtils.success(articleVO);
    }

    /**
     * 用户删除文章，只修改文章的状态
     * @param articleId 文章ID
     * @return
     *
     */
    @RequestMapping(value = "/{articleId}", method = RequestMethod.DELETE)
    public ResultVO<Object> deleteById(@PathVariable("articleId") String articleId) {
        articleService.updateStatusById(articleId, ArticleStatus.USER_DELETE.getCode());
        return ResultVoUtils.success();
    }

    /**
     * 获取文章分页信息，包含发表文章的用户信息
     * @param page 当前页
     * @param size 每页记录数
     * @return
     */
    @RequestMapping(value = "/p", method = RequestMethod.GET)
    public ResultVO<PageInfo<ArticleVO>> list(@RequestParam(value = "page", defaultValue = "1") Integer page,
                                              @RequestParam(value = "size", defaultValue = "5") Integer size) {
        PageInfo<ArticleDTO> dtoPageInfo = articleService.findPage(true, page, size);
        PageInfo<ArticleVO> voPageInfo = ArticleDTOToArticleVOConverter.convert(dtoPageInfo);
        return ResultVoUtils.success(voPageInfo);
    }

    /**
     * 获取访问量排行前N篇文章，包含发表文章的用户信息
     */
    @RequestMapping("/top/{number}")
    public ResultVO<List<ArticleVO>> getTopArticle(@PathVariable("number") Integer number) {
        List<ArticleDTO> articleDTOList = articleService.findTopListByViewCount(number);
        List<ArticleVO> articleVOList = ArticleDTOToArticleVOConverter.convert(articleDTOList);
        return ResultVoUtils.success(articleVOList);
    }
    // 实现添加的细节
    private final void saveDetail(ArticleForm articleForm, String relativePath, String realPath, MultipartFile multipartFile) {
        ArticleDTO articleDTO = new ArticleDTO();
        // 属性拷贝
        BeanUtils.copyProperties(articleForm, articleDTO);
        // 重命名文件
        String fileName = multipartFile.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        String randomKey = KeyUtils.randomKey();
        fileName = randomKey + suffix;
        // 写文件
        try {
            // 导航图文件
            File imgFile = new File(realPath + File.separator +  fileName);
            // -----------------------------------------------------------------------------------
            // 内容文件
            String contentFileName = randomKey + FileSuffixEnum.TXT_INCLUDE_POINT.getName();
            File contentFile = new File(realPath + File.separator + contentFileName);
            try(BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(contentFile))) {
                // 写内容文件
                outputStream.write(articleDTO.getArticleContent().getBytes());
            };
            // 保存内容文件相对路径
            articleDTO.setArticleContent(relativePath + contentFileName);
            // -----------------------------------------------------------------------------------
            // 写导航图
            Files.write(imgFile.toPath(), multipartFile.getBytes(), StandardOpenOption.CREATE);
            // 保存导航图相对路径
            articleDTO.setNavgationImg(relativePath + fileName);
            try {
                articleService.save(articleDTO);
            }catch (ArticleException e) {
                // 如果数据添加失败，将文件删除
                if (imgFile.exists()) {
                    imgFile.delete();
                }
                if (contentFile.exists()) {
                    contentFile.delete();
                }
                log.error("【创建文章】添加数据失败：articleDTO={}", articleDTO);
                throw e;
            }
        } catch (IOException e) {
            log.error("【创建文章】上传图片失败：multipartFile={}", multipartFile);
            throw new ArticleException(ResultEnum.ARTICLE_IMG_ERROR);
        }
    }

}
